<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns="http://relaxng.org/ns/structure/1.0"
	xmlns:rng="http://relaxng.org/ns/structure/1.0"
	version="1.0"
	xmlns:exsl="http://exslt.org/common" 
	extension-element-prefixes="exsl" 
	exclude-result-prefixes = "exsl rng"
	>
	 <xsl:strip-space elements="*"/>
	 <xsl:variable name="emptyStack">
	 	<stack/>
	 </xsl:variable>
   <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
	 
	 <xsl:template match="/">
		<grammar datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
			<start>
				<xsl:apply-templates select="//Foundation.Core.Class[Foundation.Core.GeneralizableElement.isRoot/@xmi.value='true']"/>
			</start>
		</grammar>
	 </xsl:template>

	 <xsl:template match="Foundation.Core.Class">
	 	<xsl:param name="stack" select="exsl:node-set($emptyStack)"/>
		<xsl:variable name="name" select="normalize-space(Foundation.Core.ModelElement.name)"/>
		<xsl:if test="not($stack//*=$name)">
			<xsl:variable name="newStack">
				<stack>
					<elt><xsl:value-of select="$name"/></elt>
					<xsl:copy-of select="$stack/*/*"/>
				</stack>
			</xsl:variable>
			<xsl:variable name="toGen">
				<xsl:apply-templates select="Foundation.Core.Classifier.feature/Foundation.Core.Attribute">
					<xsl:with-param name="stack" select="exsl:node-set($newStack)"/>
				</xsl:apply-templates>
				<xsl:apply-templates select="//Foundation.Core.AssociationEnd[Foundation.Core.AssociationEnd.type/Foundation.Core.Classifier/@xmi.idref=current()/@xmi.id]">
					<xsl:with-param name="stack" select="exsl:node-set($newStack)"/>
				</xsl:apply-templates>
			</xsl:variable>
			<element name="{$name}">
				<xsl:choose>
					<xsl:when test="exsl:node-set($toGen)/rng:data">
						<xsl:copy-of select="$toGen"/>
					</xsl:when>
					<xsl:otherwise>
						<interleave>
							<xsl:copy-of select="$toGen"/>
						</interleave>
					</xsl:otherwise>
				</xsl:choose>
			</element>
		</xsl:if>
	 </xsl:template>
	 
	 <xsl:template match="Foundation.Core.Attribute[starts-with(Foundation.Core.ModelElement.name, '@')]">
		<xsl:variable name="name" select="normalize-space(substring-after(Foundation.Core.ModelElement.name, '@'))"/>
		<attribute name="{$name}">
			<data type="{substring-after(//Foundation.Core.DataType[@xmi.id=current()/Foundation.Core.StructuralFeature.type/Foundation.Core.Classifier/@xmi.idref]/Foundation.Core.ModelElement.name, ':')}"/>
		</attribute>
	 </xsl:template>
	 
	 <xsl:template match="Foundation.Core.Attribute">
		<xsl:variable name="name" select="normalize-space(Foundation.Core.ModelElement.name)"/>
		<element name="{$name}">
			<data type="{substring-after(//Foundation.Core.DataType[@xmi.id=current()/Foundation.Core.StructuralFeature.type/Foundation.Core.Classifier/@xmi.idref]/Foundation.Core.ModelElement.name, ':')}"/>
		</element>
	 </xsl:template>
	 
	 <xsl:template match="Foundation.Core.Attribute[Foundation.Core.ModelElement.name = 'rng:data']">
		<data type="{substring-after(//Foundation.Core.DataType[@xmi.id=current()/Foundation.Core.StructuralFeature.type/Foundation.Core.Classifier/@xmi.idref]/Foundation.Core.ModelElement.name, ':')}"/>
	 </xsl:template>
	 
	 <xsl:template match="Foundation.Core.AssociationEnd">
	 	<xsl:param name="stack"/>
		<xsl:variable name="otherEnd" select="preceding-sibling::Foundation.Core.AssociationEnd/Foundation.Core.AssociationEnd.type/Foundation.Core.Classifier/@xmi.idref|following-sibling::Foundation.Core.AssociationEnd/Foundation.Core.AssociationEnd.type/Foundation.Core.Classifier/@xmi.idref"/>
		<xsl:variable name="embedded">
			<xsl:apply-templates select="//Foundation.Core.Class[@xmi.id=$otherEnd]">
				<xsl:with-param name="stack" select="$stack"/>
			</xsl:apply-templates>
		</xsl:variable>
		<xsl:if test="exsl:node-set($embedded)/*">
			<xsl:variable name="multiplicity">
				<xsl:apply-templates select="Foundation.Core.AssociationEnd.multiplicity/Foundation.Data_Types.Multiplicity" mode="multiplicity"/>
			</xsl:variable>
			<xsl:choose>
				<xsl:when test="$multiplicity = '0-1'">
					<zeroOrMore>
						<xsl:copy-of select="$embedded"/>
					</zeroOrMore>
				</xsl:when>
				<xsl:when test="$multiplicity = '11'">
					<xsl:copy-of select="$embedded"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:message terminate="yes">
						<xsl:text>Unsupported cardinality: </xsl:text>
						<xsl:value-of select="Foundation.Core.AssociationEnd.multiplicity"/>
						<xsl:text> for </xsl:text>
						<xsl:value-of select="@xmi.id"/>
					</xsl:message>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
	 </xsl:template>
	 
	 <xsl:template match="Foundation.Data_Types.Multiplicity[@xmi.id]" mode="multiplicity">
	 	<xsl:value-of select="."/>
	 </xsl:template>
	 <xsl:template match="Foundation.Data_Types.Multiplicity" mode="multiplicity">
	 	<xsl:apply-templates select="//Foundation.Data_Types.Multiplicity[@xmi.id=current()/@xmi.idref]" mode="multiplicity"/>
	 </xsl:template>
</xsl:stylesheet>
